package com.example.springboot.service;

import com.example.springboot.entity.*;
import com.example.springboot.mapper.ContainerMapper;
import com.example.springboot.mapper.TruckOrderMapper;
import com.example.springboot.mapper.YardMapper;
import com.example.springboot.utils.YardUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @Author: jyf2000jyf
 * @Date: 2022/5/12
 * @Time: 9:00
 * @Email: 904593011@qq.com
 * @Description:
 **/
@Service
public class UserOrderServiceImpl implements UserOrderService {
    @Autowired
    TruckOrderMapper orderMapper;

    @Autowired
    UserService userService;

    @Autowired
    ContainerMapper containerMapper;

    @Autowired
    YardMapper yardMapper;

    @Override
    public Integer save(TruckOrder order) {
        order.setDamount(order.getNormal() + order.getEmpty() + order.getHeavy() + order.getFreeze() + order.getDanger() + order.getOverweight());
        if (order.getId() == null) {  // user没有id，则表示是新增
            Date date = new Date();
            order.setUpdateTime(date);
            if (order.getArrangeTime() == null) {
                Calendar calendar = new GregorianCalendar();
                calendar.setTime(date);
                calendar.add(calendar.DATE, 1);
                order.setArrangeTime(calendar.getTime());
            }
            if (insertContainerByTruckOrder(order) && order.getType() == 0) {
                order.setStatus((byte) 1);
            }
            int result = orderMapper.insertSelective(order);
            ContainerExample containerExample = new ContainerExample();
            containerExample.createCriteria().andTruckOrderIsNull().andShipOrderIsNull();
            Container container = new Container();
            container.setTruckOrder(order.getId());
            containerMapper.updateByExampleSelective(container, containerExample);
            return result;
        } else { // 否则为更新
            order.setUpdateTime(new Date());
            if (order.getType() == 0) {
                deleteContainerByTruckOrder(order);
                if (insertContainerByTruckOrder(order) && order.getType() == 0) {
                    order.setStatus((byte) 1);
                }
            }
            int result = orderMapper.updateByPrimaryKeySelective(order);
            ContainerExample containerExample = new ContainerExample();
            containerExample.createCriteria().andTruckOrderIsNull().andShipOrderIsNull();
            Container container = new Container();
            container.setTruckOrder(order.getId());
            containerMapper.updateByExampleSelective(container, containerExample);
            return result;
        }
    }

    private boolean insertContainerByTruckOrder(TruckOrder order) {
        if (order.getNormal() != null && order.getNormal() != 0) {
            boolean status = malloc("普通箱", order.getDestination(), order.getNormal(), order.getUserId());
            if (!status) {
                return false;
            }
        }
        if (order.getEmpty() != null && order.getEmpty() != 0) {
            boolean status = malloc("空箱", order.getDestination(), order.getEmpty(), order.getUserId());
            if (!status) {
                return false;
            }
        }
        if (order.getHeavy() != null && order.getHeavy() != 0) {
            boolean status = malloc("重箱", order.getDestination(), order.getHeavy(), order.getUserId());
            if (!status) {
                return false;
            }
        }
        if (order.getFreeze() != null && order.getFreeze() != 0) {
            boolean status = malloc("冷冻箱", order.getDestination(), order.getFreeze(), order.getUserId());
            if (!status) {
                return false;
            }
        }
        if (order.getDanger() != null && order.getDanger() != 0) {
            boolean status = malloc("危险箱", order.getDestination(), order.getDanger(), order.getUserId());
            if (!status) {
                return false;
            }
        }
        if (order.getOverweight() != null && order.getOverweight() != 0) {
            boolean status = malloc("超重箱", order.getDestination(), order.getOverweight(), order.getUserId());
            if (!status) {
                return false;
            }
        }
        return true;
    }

    private boolean malloc(String containerType, String destination, Integer amount, Integer userId) {
        Integer yard = YardUtils.judgeYard(containerType, destination);
        Integer full = amount / 3;
        Integer notFull = amount % 3;
        // 处理full
        YardExample example1 = new YardExample();
        example1.setOrderByClause("row asc, `column` asc");
        example1.createCriteria().andRegionEqualTo(yard).andHeightEqualTo(0);
        List<Yard> yards1 = yardMapper.selectByExample(example1);
        if (yards1 == null || yards1.size() < full) {
            return false;
        }
        List<Yard> yards2;
        List<Yard> yards3;
        YardExample example2 = new YardExample();
        example2.setOrderByClause("height desc, row asc, `column` asc");
        example2.createCriteria().andRegionEqualTo(yard).andHeightLessThanOrEqualTo(3 - notFull).andHeightGreaterThan(0);
        yards2 = yardMapper.selectByExample(example2);
        YardExample example3 = new YardExample();
        example3.setOrderByClause("row asc, `column` asc");
        example3.createCriteria().andRegionEqualTo(yard).andHeightEqualTo(0);
        yards3 = yardMapper.selectByExample(example3);
        if (yards2.size() + yards3.size() <= full) {
            return false;
        }
        // 已经确定能放下
        for (int i = 0; i < full; i++) {
            if (notFull != 0) {
                yards3.remove(i);
            }
            Yard yard1 = yards1.get(i);
            yardMapper.updateByPrimaryKeyEqualsThree(yard1);
            Container container = new Container();
            container.setRow(yard1.getRow());
            container.setColumn(yard1.getColumn());
            container.setYard(yard1.getRegion());
            container.setUserId(userId);
            for (int j = 1; j < 4; j++) {
                container.setFloor(j);
                containerMapper.insertSelective(container);
            }
        }
        if (yards3.size() != 0) {
            for (Yard yard3 : yards3) {
                yards2.add(yard3);
            }
        }
        Yard yard2 = yards2.get(0);
        YardKey yardKey = new YardKey();
        yardKey.setRegion(yard2.getRegion());
        yardKey.setRow(yard2.getRow());
        yardKey.setColumn(yard2.getColumn());
        int i = yardMapper.selectByPrimaryKey(yardKey).getHeight();
        i += 1;
        Container container = new Container();
        container.setRow(yard2.getRow());
        container.setColumn(yard2.getColumn());
        container.setYard(yard2.getRegion());
        container.setUserId(userId);
        int j = notFull;
        for (; j > 0; j--, i++) {
            container.setFloor(i);
            containerMapper.insertSelective(container);
        }
        yard2.setHeight(notFull);
        yardMapper.updateByPrimaryKeyAddNotFull(yard2);
        return true;
    }

    private void deleteContainerByTruckOrder(TruckOrder order) {
        ContainerExample example = new ContainerExample();
        example.createCriteria().andTruckOrderEqualTo(order.getId());
        List<Container> containers = containerMapper.selectByExample(example);
        for (Container container : containers) {
            Yard yard = new Yard();
            yard.setRow(container.getRow());
            yard.setColumn(container.getColumn());
            yard.setRegion(container.getYard());
            yardMapper.updateByPrimaryKeySubOne(yard);
        }
        containerMapper.deleteByExample(example);
    }

    @Override
    public List<TruckOrder> findAll(String username) {
        TruckOrderExample example = new TruckOrderExample();
        example.createCriteria().andUserIdEqualTo(userService.getUserIdByUsername(username));
        return orderMapper.selectByExample(example);
    }

    @Override
    public Integer delete(Integer id) {
        TruckOrder truckOrder = orderMapper.selectByPrimaryKey(id);
        deleteContainerByTruckOrder(truckOrder);
        return orderMapper.deleteByPrimaryKey(id);
    }

    @Override
    public List<TruckOrder> findAll(Integer pageNum, Integer pageSize, String company, Integer status, String username) {
        TruckOrderExample example = new TruckOrderExample();
        TruckOrderExample.Criteria criteria = example.createCriteria();
        example.setOrderByClause("id desc limit " + pageNum + "," + pageSize);
        if (company != null && !"".equals(company)) {
            criteria.andCompanyLike("%" + company + "%");
        }
        if (status != null && !status.equals(-1)) {
            criteria.andStatusEqualTo(status.byteValue());
        }
        criteria.andUserIdEqualTo(userService.getUserIdByUsername(username));
        return orderMapper.selectByExample(example);
    }

    @Override
    public Integer getAmount(String company, Integer status, String username) {
        TruckOrderExample example = new TruckOrderExample();
        TruckOrderExample.Criteria criteria = example.createCriteria();
        if (company != null && !"".equals(company)) {
            criteria.andCompanyLike("%" + company + "%");
        }
        if (status != null && !status.equals(-1)) {
            criteria.andStatusEqualTo(status.byteValue());
        }
        criteria.andUserIdEqualTo(userService.getUserIdByUsername(username));
        return (Integer) (int) orderMapper.countByExample(example);
    }
}
